package tests.game;

import static org.junit.Assert.*;
import game.Group;
import game.Tile;
import game.Tile.TileColor;
import game.exceptions.GroupException;
import game.exceptions.SetException;
import game.exceptions.TileException;

import java.util.Vector;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * Tests for Group class.
 * @author Fishman Yevgeny
 * @date Oct 28, 2009
 */
public class GroupTest {

	private int _number;
	private Vector<Tile> _tTiles = new Vector<Tile>();
	
	@Before
	public void setUp(){
		this._number = 5;
		this._tTiles = new Vector<Tile>();
		
		//Test creation of correct group.
		try {
			_tTiles.add(new Tile(_number,TileColor.BLACK));
			_tTiles.add(new Tile(_number,TileColor.BLUE));
			_tTiles.add(new Tile(_number,TileColor.RED));
		} catch (TileException e) {
			fail("Exception while creating new Tile." +
				 "Message: " + e.getMessage());
		}
	}
	
	@After
	public void tearDown(){
		
	}
	
	@Test
	public void testGroup() {
		try {
			Group tGroup1 = new Group(_number,_tTiles);
			assertEquals("Group was created with wrong number.",_number,tGroup1.getNumber());
			assertEquals("Group was created with wrong number of tiles.",3,tGroup1.getTilesCount());
			assertEquals("Group was created with wrong tile.", 
					     new Tile(_number,TileColor.BLACK), tGroup1.getTileAt(0));
			assertEquals("Group was created with wrong tile.", 
				     new Tile(_number,TileColor.BLUE), tGroup1.getTileAt(1));
			assertEquals("Group was created with wrong tile.", 
				     new Tile(_number,TileColor.RED), tGroup1.getTileAt(2));
		} catch (GroupException e) {
			fail("Exception while creating new Group." +
			     "Message: " + e.getMessage());
		} catch (TileException e) {
			fail("Exception while creating new Tile." +
				     "Message: " + e.getMessage());
		} catch (SetException e) {
			fail("Exception while creating new Group." +
				     "Message: " + e.getMessage());
		} 
		
		//Test exceptions while creating not correct group.
		//Only two tiles:
		_tTiles.remove(0);
		try {
			new Group(_number, _tTiles);
			fail("Group exception was not thrown while trying to create group of two tiles.");
		} catch (GroupException e) {
			fail("Group exception was thrown while trying to create new Group with only two tiles.");
		} catch (SetException e) {
			System.out.println(e.getMessage());
		}
		
		//Same color appears more that once.
		try {
			_tTiles.add(new Tile(_number,TileColor.BLUE));
			new Group(_number, _tTiles);
			fail("Group exception was not thrown while trying to create group with two tiles with same color.");
		} catch (TileException e) {
			fail("Exception while creating new Tile." +
			     "Message: " + e.getMessage());
		} catch (GroupException e){
			System.out.println(e.getMessage());
		} catch (SetException e) {
			fail("Exception while creating new Group." +
				     "Message: " + e.getMessage());
		}
		
		//Tile with different number added.
		_tTiles.remove(2);
		try{
			_tTiles.add(new Tile(7,TileColor.YELOW));
			new Group(_number, _tTiles);
			fail("Group exception was not thrown while trying to create group from tiles with different numbers.");
		}catch(TileException e){
			fail("Exception while creating new Tile." +
				     "Message: " + e.getMessage());
		}catch(GroupException e){
			System.out.println(e.getMessage());
		} catch (SetException e) {
			fail("Exception while creating new Group." +
				     "Message: " + e.getMessage());
		}
		
	}

	@Test
	public void testAddTile() {
		
		try{
			Group tGroup = new Group(_number,_tTiles);
			//Adding legal tile.
			try{
				tGroup.addTile(new Tile(_number,TileColor.YELOW));
			}catch(GroupException e){
				fail("Exception was thrown while adding legal tile.");
			}catch(TileException e){
				fail("Exception while creating new Tile." +
					 "Message: " + e.getMessage());
			}
			
			_tTiles.remove(3);
			tGroup = new Group(_number,_tTiles);
			//Adding tile with already existing color.
			try{
				tGroup.addTile(new Tile(_number, TileColor.RED));
				fail("Exception wasn't thrown while adding tile with already existing color to a group.");
			}catch(GroupException e){
				System.out.println(e.getMessage());
			}catch(TileException e){
				fail("Exception while creating new Tile." +
				     "Message: " + e.getMessage());
			}
			
			//Adding tile with different number.
			try{
				tGroup.addTile(new Tile(6,TileColor.YELOW));
				fail("Exception was not thrown while trying to add tile with different number.");
			}catch(GroupException e){
				System.out.println(e.getMessage());
			}catch(TileException e){
				fail("Exception while creating new Tile." +
					     "Message: " + e.getMessage());
			}
			
		}catch(GroupException e){
			fail("Exception while creating new Group." +
				     "Message: " + e.getMessage());
		}catch (SetException e) {
			fail("Exception while creating new Group." +
				     "Message: " + e.getMessage());
		}	
	}

	@Test
	public void testRemoveTile() {
		try{
			_tTiles.add(new Tile(_number, TileColor.YELOW));
			try {
				//Removing existing tile.
				Group tGroup = new Group(_number, _tTiles);
				try{
					tGroup.removeTile(new Tile(_number, TileColor.BLUE));
					assertTrue("Target Group still have the removed tile.",
							   !tGroup.getTileAt(1).equals(new Tile(_number,TileColor.BLUE)));
				}catch(SetException e){
					fail("Exception while removing existing tile from a group.");
				}
				
				//Removing non-existing tile.
				_tTiles.add(new Tile(_number,TileColor.BLUE));
				tGroup = new Group(_number,_tTiles);
				try{
					tGroup.removeTile(new Tile(7,TileColor.YELOW));
					fail("Exception was not thrown while trying to remove non-existing tile.");
				}catch(SetException e){
					System.out.println(e.getMessage());
				}
				
				//Removing tile from a group with only 3 tiles.
				_tTiles.remove(new Tile(_number,TileColor.YELOW));
				tGroup = new Group(_number,_tTiles);
				try{
					tGroup.removeTile(new Tile(_number,TileColor.BLUE));
					fail("Exception was not thrown while trying to remove tile from group with 3 tiles.");
				}catch(SetException e){
					System.out.println(e.getMessage());
				}
				assertTrue("Number of tile in the group became 2 after removing a tile from group of 3.",
						   tGroup.getTilesCount() >= 3);
				
			} catch (GroupException e) {
				fail("Exception while creating new Group.");
			}
			
		}catch(TileException e){
			fail("Exception while creating new Tile." +
				     "Message: " + e.getMessage());
		}catch (SetException e) {
			fail("Exception while creating new Group." +
				     "Message: " + e.getMessage());
		}
	}
	
	@Test
	public void testContainsTile() {
		try {
			Group tGroup = new Group(_number, _tTiles);
			assertTrue("Contains returned false on an existing tile.", tGroup
					.contains(new Tile(_number, TileColor.BLUE)));
			assertTrue("Contains returned true on non-existing tile.", !tGroup
					.contains(new Tile(_number, TileColor.YELOW)));

		} catch (TileException e) {
			fail("Exception while creating new Tile." + "Message: "
					+ e.getMessage());
		} catch (GroupException e) {
			fail("Exception while creating new Group." + "Message: "
					+ e.getMessage());
		} catch (SetException e) {
			fail("Exception while creating new Group." +
				     "Message: " + e.getMessage());
		}

	}

}
